package com.yanqu.road.dao.dbV2;


import com.mysql.jdbc.JDBC4PreparedStatement;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DBManager;
import com.yanqu.road.utils.config.Config;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;

public class Database {
    private final DBManager db;

    private String dbUrl;

    private final Map<Class<?>, Table> tableMap = new HashMap<>();

    public Database(DBManager dbManager, String dbUrl) {
        this.db = dbManager;
        this.dbUrl = dbUrl;
    }

    public void register(Class<?> cls) {

        Table table = new Table(cls, dbUrl);
        this.tableMap.put(cls, table);
        if (Config.isMigrate()) {
            this.migrate(table);

            String packageName = cls.getPackage().getName();
            String path = getClass().getResource("/").getPath();
            path = path.replace("target/classes/", "src/");
            String packagePath = packageName.replaceAll("\\.", "/");
            path = path + packagePath;

            String daoPath = path + "/dao";
            File file1 = new File(daoPath);
            boolean exists = file1.exists();
            if (!exists) {
                boolean mkdirs = file1.mkdirs();
            }


            String implPath = String.format("%s/%s.Java", daoPath, table.getImplClassName());
            File implFile = new File(implPath);
            boolean exists1 = implFile.exists();
            if (exists1) {
                return;
            }


            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(String.format("package %s.dao;\n", packageName));

            //import

            stringBuilder.append("import com.yanqu.road.dao.impl.TempDataObjectDao;\n");
            stringBuilder.append("import com.yanqu.road.dao.db.DbParameter;\n");
            stringBuilder.append("import com.yanqu.road.dao.dbV2.serializer.Helper;\n");
            stringBuilder.append("import java.util.HashMap;\n");
            stringBuilder.append("import java.util.Map;\n");
            stringBuilder.append("import java.sql.*;\n");
            stringBuilder.append("import com.fasterxml.jackson.core.type.TypeReference;\n");
            stringBuilder.append(String.format("import %s;\n", cls.getName()));

            stringBuilder.append(String.format("public class %s extends TempDataObjectDao<%s> {\n", table.getImplClassName(), cls.getSimpleName()));
            stringBuilder.append(String.format("\tpublic static %s getInstance() {\n", table.getImplClassName()));
            stringBuilder.append(String.format("\t\treturn new %s();\n", table.getImplClassName()));
            stringBuilder.append("\t}\n");
            stringBuilder.append("/* 创建数据库\n");
            stringBuilder.append(String.format("\t%s\n", table.getCreateTableSql()));
            stringBuilder.append("*/\n");

            stringBuilder.append(table.getUpdateContent());
            stringBuilder.append(table.getAddContent());
            stringBuilder.append(table.getParseDataContent());
            stringBuilder.append("}");

            try {
                boolean b = implFile.createNewFile();
                if (!b) {
                    return;
                }
                try (FileOutputStream fileOutputStream = new FileOutputStream(implFile)) {
                    fileOutputStream.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
                    fileOutputStream.flush();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }


        }

    }


    public void migrate(Table table) {

        if (Config.isDebug()) {
            System.out.println(table.getCreateTableSql());
        }
        try {
            //db.setConnName(DbNameStrategy.getLogDb());
            this.db.setConnName(this.dbUrl);
            Statement statement = this.db.getConnection().createStatement();
            statement.executeUpdate(table.getCreateTableSql());
            this.db.closeConnection(statement);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }


}
